//
//  SpectraView.swift
//  DrawBarChart
//
//  Created by xiong on 2024/11/18.
//

import UIKit
func rgba(_ r: CGFloat,_ g: CGFloat, _ b: CGFloat, _ a: CGFloat) -> UIColor {
    return UIColor(red: r/255, green: g/255, blue: b/255, alpha: a)
}

class SpectraView: UIView {
    
    var barWidth: CGFloat = 20.0
    var space: CGFloat = 20.0
    
    var barLayer = CAGradientLayer()
    
    var spectra: [[Float]]? {
        didSet {
            guard let spectra = spectra else { return }
            updateGradientAndBars(spectra: spectra)
        }
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupView()
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setupView()
    }
    
    private func setupView() {
        configureGradientLayer(layer: barLayer, colors: [
            rgba(214, 0, 126, 1).cgColor, rgba(214, 0, 126, 0.5).cgColor,rgba(214, 0, 126, 0.1).cgColor], locations: [0.1, 1.0])
        self.layer.addSublayer(barLayer)
    }
    
    private func configureGradientLayer(layer: CAGradientLayer, colors: [CGColor], locations: [NSNumber]) {
        layer.colors = colors
        layer.locations = locations
        layer.frame = CGRect(x: 0, y: 0, width: bounds.width, height: bounds.height)
    }
    
    private func updateGradientAndBars(spectra: [[Float]]) {
        let path = UIBezierPath()
        
        for (i, amplitude) in spectra[0].enumerated() {
            let x = CGFloat(i) * (barWidth + space) + space
            let y = translateAmplitudeToYPosition(amplitude: amplitude)
            let bar = UIBezierPath(roundedRect: CGRect(x: x, y: y, width: barWidth, height: bounds.height - y), cornerRadius: barWidth/2)
            path.append(bar)
        }
        
        let layer = CAShapeLayer()
        layer.path = path.cgPath
        barLayer.mask = layer
    }
    
    private func translateAmplitudeToYPosition(amplitude: Float) -> CGFloat {
        let barHeight: CGFloat = CGFloat(amplitude) * (bounds.height)
        return bounds.height - barHeight
    }
}
